<template>
  <div ref="container" class="scene-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as dat from "dat.gui";
/**
 * 点光源
 */
// 给当前组件定义名称
defineOptions({
  name: "ThreeScene",
});

const container = ref<HTMLElement>();
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let sphere: THREE.Mesh;
let plane: THREE.Mesh;
let spotLight: THREE.SpotLight;
let smallBall: THREE.Mesh;
//设置时钟
let clock = new THREE.Clock();
// 初始化场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x333333); // 设置较暗的背景色
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, 5, 10);

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  container.value?.appendChild(renderer.domElement);

  // 创建球体
  const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
  const sphereMaterial = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    roughness: 0.5, // 粗糙度
    metalness: 0.2, // 金属度
  });
  sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.position.set(0, 1, 0);
  sphere.castShadow = true;
  scene.add(sphere);

  // 创建平面
  const planeGeometry = new THREE.PlaneGeometry(20, 20);
  const planeMaterial = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    roughness: 0.4, // 粗糙度
    metalness: 0, // 金属度
  });
  plane = new THREE.Mesh(planeGeometry, planeMaterial);
  plane.rotation.x = -Math.PI / 2;
  plane.position.y = 0;
  plane.receiveShadow = true;
  scene.add(plane);

  // 创建点光源 -- 灯光
  const pointLight = new THREE.PointLight(0xff0000, 2, 100);
  // 设置光源位置
  pointLight.position.set(1, 1, 1);
  // 开启阴影
  pointLight.castShadow = true;
  pointLight.decay = 0.5;
  // pointLight.power = 160;
  //设置阴影贴图模糊度
  pointLight.shadow.mapSize.set(2048, 2048);
  pointLight.shadow.camera.near = 0.1;
  pointLight.shadow.camera.far = 100;
  // scene.add(pointLight);

  // 添加环境光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
  scene.add(ambientLight);
  //添加小球
  smallBall = new THREE.Mesh(
    new THREE.SphereGeometry(0.1, 20, 20),
    new THREE.MeshBasicMaterial({ color: 0xff0000 })
  );
  smallBall.add(pointLight); //将小球添加到灯光上
  smallBall.position.set(2, 2, 2);
  scene.add(smallBall);

  // 添加坐标轴辅助
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);

  // 添加聚光灯辅助
  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  // scene.add(spotLightHelper);

  // 添加GUI控制
  const gui = new dat.GUI();
  const pointLightFolder = gui.addFolder("PointLight");
  pointLightFolder.add(pointLight, "intensity", 0, 5).name("强度");
  pointLightFolder.add(pointLight.position, "y", 0, 20).name("高度");
  pointLightFolder.add(pointLight.position, "x", -10, 10).name("x");
  pointLightFolder.add(pointLight, "decay", 0, 10).name("沿光照距离的衰减量");
  const sphereFolder = gui.addFolder("Sphere");
  sphereFolder.add(sphere.position, "y", -10, 10).name("y");
  sphereFolder.add(sphere.position, "x", -10, 10).name("x");
  sphereFolder.add(sphere.position, "z", -10, 10).name("z");
  // const spotLightFolder = gui.addFolder("SpotLight");
  // spotLightFolder
  //   .add(spotLight, "angle", 0, Math.PI / 2)
  //   .name("角度")
  //   .onChange(() => {
  //     spotLightHelper.update();
  //   });
  // spotLightFolder.add(spotLight, "decay", 0, 10).name("沿光照距离的衰减量");
  // spotLightFolder.add(spotLight, "penumbra", 0, 1).name("边缘软化");
  // spotLightFolder.add(spotLight, "intensity", 0, 5).name("强度");
  // spotLightFolder
  //   .add(spotLight.position, "y", 0, 20)
  //   .name("高度")
  //   .onChange(() => {
  //     spotLightHelper.update();
  //   });

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.5;

  // 开始动画循环
  animate();
};

// 动画循环函数
const animate = () => {
  let time = clock.getElapsedTime();
  smallBall.position.x = Math.sin(time) * 3; // 小球的x轴
  smallBall.position.z = Math.cos(time) * 3; // 小球的z轴
  smallBall.position.y = 2 + Math.sin(time * 10); // 小球的高度
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
};

// 处理窗口大小变化
const handleResize = () => {
  if (camera && renderer) {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
};

// 组件挂载时初始化
onMounted(() => {
  initScene();
  window.addEventListener("resize", handleResize);
});

// 组件卸载时清理
onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
});
</script>

<style scoped>
.scene-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
</style>
